package com.zhaokuner.springboot.config;

import lombok.extern.log4j.Log4j2;
import org.springframework.boot.env.PropertiesPropertySourceLoader;
import org.springframework.boot.env.YamlPropertySourceLoader;
import org.springframework.core.env.PropertySource;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.EncodedResource;
import org.springframework.core.io.support.PropertySourceFactory;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * 用法： <br>
 * PropertySourceFactory的加载时机早于Spring Beans容器所以独立加载用于参数入spring环境，优先级低于application.yml <br>
 * 根据name属性添加一个<br>
 * 以下是@实例<br>
 * Configuration <br>
 * PropertySource(value = "classpath:application-framework-httpclient.yml", name =
 * "classpath:application-framework-httpclient.yml", factory =FrameworkPropertySourceFactory.class)
 * @author zhaokuner
 */
@Log4j2
public class FrameworkPropertySourceFactory implements PropertySourceFactory {


    private final String suffixYml = ".yml";
    private final String suffixProperties = ".properties";

    /**
     * @param name            PropertySource 中的name
     * @param encodedResource PropertySource 中的value
     * @return
     * @throws IOException
     */
    @Override
    public PropertySource<?> createPropertySource(String name, EncodedResource encodedResource) throws IOException {
       log.info("FrameworkPropertySourceFactory加载配置文件start加载[" + name + "]");
        Resource resource = encodedResource.getResource();
        String value = resource.getFilename();
        if (!resource.exists()) {
            log.info("FrameworkPropertySourceFactory加载配置文件失败[资源不存在尝试name][name]" + name + "[value]" + value);
            if (null != name && !name.isEmpty()) {
                try {
                    DefaultResourceLoader defaultResourceLoader = new DefaultResourceLoader();
                    resource = defaultResourceLoader.getResource(name);
                } catch (Exception ex) {
                    log.info("FrameworkPropertySourceFactory加载配置文件失败[name]" + name + "[value]" + value,ex);
                    return replaceNull(name);
                }
            }

            if (!resource.exists()) {
                log.info("FrameworkPropertySourceFactory加载配置文件失败[资源不存在][name]" + name + "[value]" + value);
                return replaceNull(name);
            }
        }
        String fileName = resource.getFilename();

        try {

            List<PropertySource<?>> list = new ArrayList<>();
            if (fileName.endsWith(suffixYml)) {
                YamlPropertySourceLoader ymlLoader = new YamlPropertySourceLoader();
                list = ymlLoader.load(name, resource);
            } else if (fileName.endsWith(suffixProperties)) {
                PropertiesPropertySourceLoader propertiesLoader = new PropertiesPropertySourceLoader();
                list = propertiesLoader.load(name, resource);
            }

            if (list.isEmpty()) {
                return replaceNull(name);
            }
            log.info("FrameworkPropertySourceFactory加载配置文件success加载[" + name + "]");
            return list.get(0);

        } catch (Throwable e) {
            log.info("FrameworkPropertySourceFactory加载配置文件失败[异常][name]" + name + "[value]" + resource.getFilename(), e);
            return replaceNull(name);
        }
    }

    /**
     * 单个jar配置不起作用时不保存，打印异常日志
     *
     * @param name
     * @return
     */
    private PropertySource<?> replaceNull(String name) {
        return new PropertySource<Object>(name) {
            @Override
            public Object getProperty(String s) {
                return null;
            }
        };
    }

}